home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 8 / Night Owl CD-ROM (NOPV8) (Night Owl Publisher) (1993).ISO / 017a / binutils.arj / CPLUS-DE.C < prev    next >
C/C++ Source or Header  |  1992-03-29  |  28KB  |  1,351 lines

  1. /* Demangler for GNU C++ 
  2.    Copyright (C) 1989, 1992 Free Software Foundation, Inc.
  3.    written by James Clark (jjc@jclark.uucp)
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* This is for g++ 1.36.1 (November 6 version). It will probably
  20.    require changes for any other version.
  21.  
  22.    Modified for g++ 1.36.2 (November 18 version).
  23.  
  24.    Modified for g++ 1.90.06 (December 31 version).
  25.  
  26.    Modified for g++ 1.95.03 (November 13 version).  */
  27.  
  28. /* This file exports one function
  29.  
  30.    char *cplus_demangle (const char *name)
  31.  
  32.    If NAME is a mangled function name produced by GNU C++, then
  33.    a pointer to a malloced string giving a C++ representation
  34.    of the name will be returned; otherwise NULL will be returned.
  35.    It is the caller's responsibility to free the string which
  36.    is returned.
  37.  
  38.    For example,
  39.    
  40.    cplus_demangle ("_foo__1Ai")
  41.    
  42.    returns
  43.  
  44.    "A::foo(int)"
  45.  
  46.    This file imports xmalloc and xrealloc, which are like malloc and
  47.    realloc except that they generate a fatal error if there is no
  48.    available memory. */
  49.  
  50. /* #define nounderscore 1 /* define this is names don't start with _ */
  51.  
  52. #include <stdio.h>
  53. #include <ctype.h>
  54.  
  55. #ifdef USG
  56. #include <memory.h>
  57. #include <string.h>
  58. #else
  59. #include <strings.h>
  60. #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
  61. #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
  62. #define strchr index 
  63. #define strrchr rindex
  64. #endif
  65.  
  66. /* This is '$' on systems where the assembler can deal with that.
  67.    Where the assembler can't, it's '.' (but on many systems '.' is
  68.    used for other things).  */
  69. #if !defined (CPLUS_MARKER)
  70. #define CPLUS_MARKER '$'
  71. #endif
  72.  
  73. #ifndef __STDC__
  74. #define const
  75. #endif
  76.  
  77. #ifdef __STDC__
  78. extern char *cplus_demangle (const char *type);
  79. #else
  80. extern char *cplus_demangle ();
  81. #endif
  82.  
  83. #ifdef __STDC__
  84. extern char *xmalloc (int);
  85. extern char *xrealloc (char *, int);
  86. extern void free (void *);
  87. #else
  88. extern char *xmalloc ();
  89. extern char *xrealloc ();
  90. extern void free ();
  91. #endif
  92.  
  93. static char **typevec = 0;
  94. static int ntypes = 0;
  95. static int typevec_size = 0;
  96.  
  97. static struct {
  98.   const char *in;
  99.   const char *out;
  100. } optable[] = {
  101.   "nw", " new",            /* new (1.92, ansi) */
  102.   "dl", " delete",        /* new (1.92, ansi) */
  103.   "new", " new",        /* old (1.91) */
  104.   "delete", " delete",        /* old (1.91) */
  105.   "ne", "!=",            /* old, ansi */
  106.   "eq", "==",            /* old, ansi */
  107.   "ge", ">=",            /* old, ansi */
  108.   "gt", ">",            /* old, ansi */
  109.   "le", "<=",            /* old, ansi */
  110.   "lt", "<",            /* old, ansi */
  111.   "plus", "+",            /* old */
  112.   "pl", "+",            /* ansi */
  113.   "apl", "+=",            /* ansi */
  114.   "minus", "-",            /* old */
  115.   "mi", "-",            /* ansi */
  116.   "ami", "-=",            /* ansi */
  117.   "mult", "*",            /* old */
  118.   "ml", "*",            /* ansi */
  119.   "aml", "*=",            /* ansi */
  120.   "convert", "+",        /* old (unary +) */
  121.   "negate", "-",        /* old (unary -) */
  122.   "trunc_mod", "%",        /* old */
  123.   "md", "%",            /* ansi */
  124.   "amd", "%=",            /* ansi */
  125.   "trunc_div", "/",        /* old */
  126.   "dv", "/",            /* ansi */
  127.   "adv", "/=",            /* ansi */
  128.   "truth_andif", "&&",        /* old */
  129.   "aa", "&&",            /* ansi */
  130.   "truth_orif", "||",        /* old */
  131.   "oo", "||",            /* ansi */
  132.   "truth_not", "!",        /* old */
  133.   "nt", "!",            /* ansi */
  134.   "postincrement", "++",    /* old */
  135.   "pp", "++",            /* ansi */
  136.   "postdecrement", "--",    /* old */
  137.   "mm", "--",            /* ansi */
  138.   "bit_ior", "|",        /* old */
  139.   "or", "|",            /* ansi */
  140.   "aor", "|=",            /* ansi */
  141.   "bit_xor", "^",        /* old */
  142.   "er", "^",            /* ansi */
  143.   "aer", "^=",            /* ansi */
  144.   "bit_and", "&",        /* old */
  145.   "ad", "&",            /* ansi */
  146.   "aad", "&=",            /* ansi */
  147.   "bit_not", "~",        /* old */
  148.   "co", "~",            /* ansi */
  149.   "call", "()",            /* old */
  150.   "cl", "()",            /* ansi */
  151.   "cond", "?:",            /* old */
  152.   "alshift", "<<",        /* old */
  153.   "ls", "<<",            /* ansi */
  154.   "als", "<<=",            /* ansi */
  155.   "arshift", ">>",        /* old */
  156.   "rs", ">>",            /* ansi */
  157.   "ars", ">>=",            /* ansi */
  158.   "component", "->",        /* old */
  159.   "rf", "->",            /* ansi */
  160.   "indirect", "*",        /* old */
  161.   "method_call", "->()",    /* old */
  162.   "addr", "&",            /* old (unary &) */
  163.   "array", "[]",        /* old */
  164.   "vc", "[]",            /* ansi */
  165.   "compound", ",",        /* old */
  166.   "cm", ",",            /* ansi */
  167.   "nop", "",            /* old (for operator=) */
  168.   "as", "=",            /* ansi */
  169. };
  170.  
  171. /* Beware: these aren't '\0' terminated. */
  172.  
  173. typedef struct {
  174.   char *b;            /* pointer to start of string */
  175.   char *p;            /* pointer after last character */
  176.   char *e;            /* pointer after end of allocated space */
  177. } string;
  178.  
  179. #ifdef __STDC__
  180. static void string_need (string *s, int n);
  181. static void string_delete (string *s);
  182. static void string_init (string *s);
  183. static void string_clear (string *s);
  184. static int string_empty (string *s);
  185. static void string_append (string *p, const char *s);
  186. static void string_appends (string *p, string *s);
  187. static void string_appendn (string *p, const char *s, int n);
  188. static void string_prepend (string *p, const char *s);
  189. #if 0
  190. static void string_prepends (string *p, string *s);
  191. #endif
  192. static void string_prependn (string *p, const char *s, int n);
  193. static int get_count (const char **type, int *count);
  194. static int do_args (const char **type, string *decl);
  195. static int do_type (const char **type, string *result);
  196. static int do_arg (const char **type, string *result);
  197. static int do_args (const char **type, string *decl);
  198. static void munge_function_name (string *name);
  199. static void remember_type (const char *type, int len);
  200. #else
  201. static void string_need ();
  202. static void string_delete ();
  203. static void string_init ();
  204. static void string_clear ();
  205. static int string_empty ();
  206. static void string_append ();
  207. static void string_appends ();
  208. static void string_appendn ();
  209. static void string_prepend ();
  210. static void string_prepends ();
  211. static void string_prependn ();
  212. static int get_count ();
  213. static int do_args ();
  214. static int do_type ();
  215. static int do_arg ();
  216. static int do_args ();
  217. static void munge_function_name ();
  218. static void remember_type ();
  219. #endif
  220.  
  221. int
  222. get_simple_count (type, res)
  223.      char **type;
  224.      int *res;
  225. {
  226.   int n = 0, success = 1;;
  227.   
  228.   do
  229.     {
  230.       n *= 10;
  231.       n += **type - '0';
  232.       *type += 1;
  233.     } 
  234.   while (isdigit (**type));
  235.   if (strlen (*type) < n)
  236.     {
  237.       success = 0;
  238.     }
  239.  
  240.   *res = n;
  241.   return success;
  242. }
  243.  
  244. char *
  245. cplus_demangle (type)
  246.      const char *type;
  247. {
  248.   string decl;
  249.   int n;
  250.   int success = 0;
  251.   int constructor = 0;
  252.   int destructor = 0;
  253.   int static_type = 0;
  254.   int const_flag = 0;
  255.   int i;
  256.   const char *p;
  257. #ifndef LONGERNAMES
  258.   const char *premangle;
  259. #endif
  260.  
  261.   if (type == NULL || *type == '\0')
  262.     return NULL;
  263. #ifndef nounderscore
  264.   if (*type++ != '_')
  265.     return NULL;
  266. #endif
  267.   p = type;
  268.   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  269.     p++;
  270.   if (*p == '\0')
  271.     {
  272.       /* destructor */
  273.       if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
  274.     {
  275.       destructor = 1;
  276.       p = type;
  277.     }
  278.       /* static data member */
  279.       else if (*type != '_' && (strchr (type, CPLUS_MARKER) != NULL))
  280.     {
  281.       static_type = 1;
  282.       p = type;
  283.     }
  284.       /* virtual table "_vt$"  */
  285.       else if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
  286.     {
  287.       int n = strlen (type + 4) + 14 + 1;
  288.       char *tem = (char *) xmalloc (n);
  289.       strcpy (tem, type + 4);
  290.       strcat (tem, " virtual table");
  291.       return tem;
  292.     }
  293.       else return NULL;
  294.     }
  295.  
  296.   string_init (&decl);
  297.  
  298.   if (static_type)
  299.     {
  300.       if (!isdigit (p[0]) && ('t' != p[0]))
  301.     {
  302.       string_delete (&decl);
  303.       return NULL;
  304.     }
  305.     }
  306.   else if (destructor)
  307.     {
  308.       if (!isdigit (p[3])&& ('t' != p[3]))
  309.     {
  310.       string_delete (&decl);
  311.       return NULL;
  312.     }
  313.       p += 3;
  314.     }
  315.   else if (p == type)
  316.     {
  317.       if (!isdigit (p[2]) && ('t' != p[2]))
  318.     {
  319.       p += 1;
  320.       while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  321.         p++;
  322.       string_appendn (&decl, type, p - type);      
  323.       string_appendn (&decl, "", 1);
  324.       munge_function_name (&decl);
  325.       if (decl.b[0] == '_')
  326.         {
  327.           string_delete (&decl);
  328.           return NULL;
  329.         }
  330.       else
  331.         p += 2;
  332.     }
  333.       else
  334.     {
  335.       constructor = 1;
  336.       p += 2;
  337.     }
  338.     }
  339.   else
  340.     {
  341.       string_appendn (&decl, type, p - type);
  342.       decl.p[0] = '0';
  343.       munge_function_name (&decl);
  344.       p += 2;
  345.     }
  346.  
  347. #ifndef LONGERNAMES
  348.   premangle = p;
  349. #endif
  350.   switch (*p)
  351.     {
  352.     case 'C':
  353.       /* a const member function */
  354.       if (!isdigit (p[1]))
  355.     {
  356.       string_delete (&decl);
  357.       return NULL;
  358.     }
  359.       p += 1;
  360.       const_flag = 1;
  361.       /* fall through */
  362.     case '0':
  363.     case '1':
  364.     case '2':
  365.     case '3':
  366.     case '4':
  367.     case '5':
  368.     case '6':
  369.     case '7':
  370.     case '8':
  371.     case '9':
  372.       n = 0;
  373.       do
  374.     {
  375.       n *= 10;
  376.       n += *p - '0';
  377.       p += 1;
  378.     }
  379.       while (isdigit (*p));
  380.       if (strlen (p) < n)
  381.     {
  382.       string_delete (&decl);
  383.       return NULL;
  384.     }
  385.       if (constructor || destructor)
  386.     {
  387.       string_appendn (&decl, p, n);
  388.       string_append (&decl, "::");
  389.       if (destructor)
  390.         string_append(&decl, "~");
  391.       string_appendn (&decl, p, n);
  392.     }
  393.       else
  394.     {
  395.       string_prepend (&decl, "::");
  396.       string_prependn (&decl, p, n);
  397.     }
  398.       p += n;
  399. #ifndef LONGERNAMES
  400.       remember_type (premangle, p - premangle);
  401. #endif
  402.       if (static_type)
  403.     {
  404.       string_append(&decl, p+1);
  405.       p += strlen(p);
  406.       success = 1;
  407.     }
  408.       else
  409.     success = do_args (&p, &decl);
  410.       if (const_flag)
  411.     string_append (&decl, " const");
  412.       break;
  413.     case 'F':
  414.       p += 1;
  415.       success = do_args (&p, &decl);
  416.       break;
  417.     /* template additions */
  418.     case 't':
  419.       p += 1;
  420.       {
  421.     int r, i;
  422.     int non_empty = 0;
  423.     string tname;
  424.     string trawname;
  425.     
  426.     string temp;
  427.     int need_comma = 0;
  428.     
  429.     string_init(&tname);
  430.     string_init(&trawname);
  431.     
  432.     /* get template name */
  433.     if (!get_simple_count (&p, &r))
  434.       {
  435.         string_delete (&decl);
  436.         return 0;
  437.       }
  438.     string_appendn (&tname, p, r);
  439.     string_appendn (&trawname, p, r);
  440.     string_appendn (&trawname, "", 1);
  441.     p += r;
  442.     string_append (&tname, "<");
  443.     /* get size of template parameter list */
  444.     if (!get_count (&p, &r))
  445.       return 0;
  446.     for (i = 0; i < r; i++)
  447.       {
  448.         if (need_comma)
  449.           string_append (&tname, ", ");
  450.         /* Z for type parameters */
  451.         if (*p == 'Z')
  452.           {
  453.         p += 1;
  454.         
  455.         success = do_type (&p, &temp);
  456.         string_appendn (&temp, "", 1);
  457.         if (success)
  458.           string_append (&tname, temp.b);
  459.         string_delete(&temp);
  460.         if (!success)
  461.           break;
  462.           }
  463.         /* otherwise, value parameter */
  464.         else
  465.           {
  466.         const char *old_p  = p;
  467.         int is_pointer = 0;
  468.         int is_real = 0;
  469.         int is_integral = 0;
  470.         int done = 0;
  471.  
  472.         success = do_type (&p, &temp);
  473.         string_appendn (&temp, "", 1);
  474.         if (success)
  475.           string_append (&tname, temp.b);
  476.         string_delete(&temp);
  477.         if (!success)
  478.           break;
  479.         string_append (&tname, "=");
  480.         while (*old_p && !done)
  481.           {    
  482.             switch (*old_p)
  483.               {
  484.               case 'P':
  485.               case 'R':
  486.             done = is_pointer = 1;
  487.             break;
  488.               case 'C':    /* const */
  489.               case 'U':    /* unsigned */
  490.               case 'V':    /* volatile */
  491.               case 'F':    /* function */
  492.               case 'M':    /* member function */
  493.               case 'O':    /* ??? */
  494.             old_p++;
  495.             continue;
  496.               case 'Q':    /* repetition of following */
  497.               case 'T':    /* remembered type */
  498.             abort();
  499.             break;
  500.               case 'v':    /* void */
  501.             abort();
  502.             break;
  503.               case 'x':    /* long long */
  504.               case 'l':    /* long */
  505.               case 'i':    /* int */
  506.               case 's':    /* short */
  507.               case 'c':    /* char */
  508.             done = is_integral = 1;
  509.             break;
  510.               case 'r':    /* long double */
  511.               case 'd':    /* double */
  512.               case 'f':    /* float */
  513.             done = is_real = 1;
  514.             break;
  515.               default:
  516.             abort();
  517.               }
  518.           }
  519.         if (is_integral)
  520.           {
  521.             if (*p == 'm')
  522.               {
  523.             string_appendn (&tname, "-", 1);
  524.             p++;
  525.               }
  526.             while (isdigit (*p))    
  527.               {
  528.             string_appendn (&tname, p, 1);
  529.             p++;
  530.               }
  531.           }
  532.         else if (is_real)
  533.           {
  534.             if (*p == 'm')
  535.               {
  536.             string_appendn (&tname, "-", 1);
  537.             p++;
  538.               }
  539.             while (isdigit (*p))    
  540.               {
  541.             string_appendn (&tname, p, 1);
  542.             p++;
  543.               }
  544.             if (*p == '.') /* fraction */
  545.               {
  546.             string_appendn (&tname, ".", 1);
  547.             p++;
  548.             while (isdigit (*p))    
  549.               {
  550.                 string_appendn (&tname, p, 1);
  551.                 p++;
  552.               }
  553.               }
  554.             if (*p == 'e') /* exponent */
  555.               {
  556.             string_appendn (&tname, "e", 1);
  557.             p++;
  558.             while (isdigit (*p))    
  559.               {
  560.                 string_appendn (&tname, p, 1);
  561.                 p++;
  562.               }
  563.               }
  564.           }
  565.         else if (is_pointer)
  566.           {
  567.             int symbol_len;
  568.             
  569.             if (!get_count (&p, &symbol_len))
  570.               {
  571.             success = 0;
  572.             break;
  573.               }
  574.             string_appendn (&tname, p, symbol_len);
  575.             p += symbol_len;
  576.           }
  577.           }
  578.         need_comma = 1;
  579.       }
  580.     string_append (&tname, ">::");
  581.     if (destructor)
  582.       string_append(&tname, "~");
  583.     if (constructor || destructor) {
  584.       string_appendn (&trawname, "", 1);
  585.       string_append (&tname, trawname.b);
  586.     }
  587.     string_delete(&trawname);
  588.     
  589.     if (!success) {
  590.       string_delete(&tname);
  591.       return 0;
  592.     }
  593.     string_appendn (&tname, "", 1);
  594.     string_prepend (&decl, tname.b);
  595.     string_delete (&tname);
  596.  
  597.     if (static_type)
  598.       {
  599.         string_append (&decl, p+1);
  600.         p += strlen (p);
  601.         success = 1;
  602.       }
  603.     else
  604.       success = do_args (&p, &decl);
  605.     break;
  606.       }
  607.     }
  608.  
  609.   for (i = 0; i < ntypes; i++)
  610.     if (typevec[i] != NULL)
  611.       free (typevec[i]);
  612.   ntypes = 0;
  613.   if (typevec != NULL)
  614.     {
  615.       free ((char *)typevec);
  616.       typevec = NULL;
  617.       typevec_size = 0;
  618.     }
  619.  
  620.   if (success)
  621.     {
  622.       string_appendn (&decl, "", 1);
  623.       return decl.b;
  624.     }
  625.   else
  626.     {
  627.       string_delete (&decl);
  628.       return NULL;
  629.     }
  630. }
  631.  
  632. static int
  633. get_count (type, count)
  634.      const char **type;
  635.      int *count;
  636. {
  637.   if (!isdigit (**type))
  638.     return 0;
  639.   *count = **type - '0';
  640.   *type += 1;
  641.   /* see flush_repeats in cp-method.c */
  642.   if (isdigit (**type))
  643.     {
  644.       const char *p = *type;
  645.       int n = *count;
  646.       do 
  647.     {
  648.       n *= 10;
  649.       n += *p - '0';
  650.       p += 1;
  651.     } 
  652.       while (isdigit (*p));
  653.       if (*p == '_')
  654.     {
  655.       *type = p + 1;
  656.       *count = n;
  657.     }
  658.     }
  659.   return 1;
  660. }
  661.  
  662. /* result will be initialised here; it will be freed on failure */
  663.  
  664. static int
  665. do_type (type, result)
  666.      const char **type;
  667.      string *result;
  668. {
  669.   int n;
  670.   int done;
  671.   int non_empty = 0;
  672.   int success;
  673.   string decl;
  674.   const char *remembered_type;
  675.  
  676.   string_init (&decl);
  677.   string_init (result);
  678.  
  679.   done = 0;
  680.   success = 1;
  681.   while (success && !done)
  682.     {
  683.       int member;
  684.       switch (**type)
  685.     {
  686.     case 'Q':
  687.       n = (*type)[1] - '0';
  688.       if (n < 0 || n > 9)
  689.         success = 0;
  690.       *type += 2;
  691.       while (n-- > 0)
  692.         do_type (type, result);
  693.       break;
  694.  
  695.     case 'P':
  696.       *type += 1;
  697.       string_prepend (&decl, "*");
  698.       break;
  699.  
  700.     case 'R':
  701.       *type += 1;
  702.       string_prepend (&decl, "&");
  703.       break;
  704.  
  705.     case 'T':
  706.       *type += 1;
  707.       if (!get_count (type, &n) || n >= ntypes)
  708.         success = 0;
  709.       else
  710.         {
  711.           remembered_type = typevec[n];
  712.           type = &remembered_type;
  713.         }
  714.       break;
  715.  
  716.     case 'F':
  717.       *type += 1;
  718.       if (!string_empty (&decl) && decl.b[0] == '*')
  719.         {
  720.           string_prepend (&decl, "(");
  721.           string_append (&decl, ")");
  722.         }
  723.       if (!do_args (type, &decl) || **type != '_')
  724.         success = 0;
  725.       else
  726.         *type += 1;
  727.       break;
  728.  
  729.     case 'M':
  730.     case 'O':
  731.       {
  732.         int constp = 0;
  733.         int volatilep = 0;
  734.  
  735.         member = **type == 'M';
  736.         *type += 1;
  737.         if (!isdigit (**type))
  738.           {
  739.         success = 0;
  740.         break;
  741.           }
  742.         n = 0;
  743.         do
  744.           {
  745.         n *= 10;
  746.         n += **type - '0';
  747.         *type += 1;
  748.           } 
  749.         while (isdigit (**type));
  750.         if (strlen (*type) < n)
  751.           {
  752.         success = 0;
  753.         break;
  754.           }
  755.         string_append (&decl, ")");
  756.         string_prepend (&decl, "::");
  757.         string_prependn (&decl, *type, n);
  758.         string_prepend (&decl, "(");
  759.         *type += n;
  760.         if (member)
  761.           {
  762.         if (**type == 'C')
  763.           {
  764.             *type += 1;
  765.             constp = 1;
  766.           }
  767.         if (**type == 'V')
  768.           {
  769.             *type += 1;
  770.             volatilep = 1;
  771.           }
  772.         if (*(*type)++ != 'F')
  773.           {
  774.             success = 0;
  775.             break;
  776.           }
  777.           }
  778.         if ((member && !do_args (type, &decl)) || **type != '_')
  779.           {
  780.         success = 0;
  781.         break;
  782.           }
  783.         *type += 1;
  784.         if (constp)
  785.           {
  786.         if (non_empty)
  787.           string_append (&decl, " ");
  788.         else
  789.           non_empty = 1;
  790.         string_append (&decl, "const");
  791.           }
  792.         if (volatilep)
  793.           {
  794.         if (non_empty)
  795.           string_append (&decl, " ");
  796.         else
  797.           non_empty = 1;
  798.         string_append (&decl, "volatile");
  799.           }
  800.         break;
  801.       }
  802.  
  803.     case 'C':
  804.       if ((*type)[1] == 'P')
  805.         {
  806.           *type += 1;
  807.           if (!string_empty (&decl))
  808.         string_prepend (&decl, " ");
  809.           string_prepend (&decl, "const");
  810.           break;
  811.         }
  812.  
  813.       /* fall through */
  814.     default:
  815.       done = 1;
  816.       break;
  817.     }
  818.     }
  819.  
  820.   non_empty = 0;
  821.   if (success)
  822.     success = do_cuv_prefix (type, result, &non_empty);
  823.  
  824.   if (success)
  825.     success = do_builtin_type(type, result, &non_empty);
  826.   
  827.   if (success)
  828.     {
  829.       if (!string_empty (&decl))
  830.     {
  831.       string_append (result, " ");
  832.       string_appends (result, &decl);
  833.     }
  834.       string_delete (&decl);
  835.       return 1;
  836.     }
  837.   else
  838.     {
  839.       string_delete (&decl);
  840.       string_delete (result);
  841.       return 0;
  842.     }
  843. }
  844.  
  845. int
  846. do_cuv_prefix (type, result, non_empty)
  847.      char **type;
  848.      string* result;
  849.      int* non_empty;
  850. {
  851.   int success = 1;
  852.   int done = 0;
  853.   
  854.   while (success && !done)
  855.     {
  856.       switch (**type)
  857.     {
  858.     case 'C':
  859.       *type += 1;
  860.       if (*non_empty)
  861.         string_append (result, " ");
  862.       else
  863.         *non_empty = 1;
  864.       string_append (result, "const");
  865.       break;
  866.     case 'U':
  867.       *type += 1;
  868.       if (*non_empty)
  869.         string_append (result, " ");
  870.       else
  871.         *non_empty = 1;
  872.       string_append (result, "unsigned");
  873.       break;
  874.     case 'V':
  875.       *type += 1;
  876.       if (*non_empty)
  877.         string_append (result, " ");
  878.       else
  879.         *non_empty = 1;
  880.       string_append (result, "volatile");
  881.       break;
  882.     default:
  883.       done = 1;
  884.       break;
  885.     }
  886.     }
  887.   return success;
  888. }
  889.  
  890. int
  891. do_builtin_type (type, result, non_empty)
  892.      char **type;
  893.      string* result;
  894.      int *non_empty;
  895. {
  896.   int success = 1;
  897.   int n;
  898.   
  899.   switch (**type)
  900.     {
  901.     case '\0':
  902.     case '_':
  903.       break;
  904.     case 'v':
  905.       *type += 1;
  906.       if (*non_empty)
  907.     string_append (result, " ");
  908.       string_append (result, "void");
  909.       break;
  910.     case 'x':
  911.       *type += 1;
  912.       if (*non_empty)
  913.     string_append (result, " ");
  914.       string_append (result, "long long");
  915.       break;
  916.     case 'l':
  917.       *type += 1;
  918.       if (*non_empty)
  919.     string_append (result, " ");
  920.       string_append (result, "long");
  921.       break;
  922.     case 'i':
  923.       *type += 1;
  924.       if (*non_empty)
  925.     string_append (result, " ");
  926.       string_append (result, "int");
  927.       break;
  928.     case 's':
  929.       *type += 1;
  930.       if (*non_empty)
  931.     string_append (result, " ");
  932.       string_append (result, "short");
  933.       break;
  934.     case 'c':
  935.       *type += 1;
  936.       if (*non_empty)
  937.     string_append (result, " ");
  938.       string_append (result, "char");
  939.       break;
  940.     case 'r':
  941.       *type += 1;
  942.       if (*non_empty)
  943.     string_append (result, " ");
  944.       string_append (result, "long double");
  945.       break;
  946.     case 'd':
  947.       *type += 1;
  948.       if (*non_empty)
  949.     string_append (result, " ");
  950.       string_append (result, "double");
  951.       break;
  952.     case 'f':
  953.       *type += 1;
  954.       if (*non_empty)
  955.     string_append (result, " ");
  956.       string_append (result, "float");
  957.       break;
  958.     case 'G':
  959.       *type += 1;
  960.       if (!isdigit (**type))
  961.     {
  962.       success = 0;
  963.       break;
  964.     }
  965.       /* fall through */
  966.     case '0':
  967.     case '1':
  968.     case '2':
  969.     case '3':
  970.     case '4':
  971.     case '5':
  972.     case '6':
  973.     case '7':
  974.     case '8':
  975.     case '9':
  976.       n = 0;
  977.       do
  978.     {
  979.       n *= 10;
  980.       n += **type - '0';
  981.       *type += 1;
  982.     }
  983.       while (isdigit (**type));
  984.       if (strlen (*type) < n)
  985.     {
  986.       success = 0;
  987.       break;
  988.     }
  989.       if (*non_empty)
  990.     string_append (result, " ");
  991.       string_appendn (result, *type, n);
  992.       *type += n;
  993.       break;
  994.     default:
  995.       success = 0;
  996.       break;
  997.     }
  998.   return success;
  999. }
  1000.  
  1001. /* `result' will be initialised in do_type; it will be freed on failure */
  1002.  
  1003. static int
  1004. do_arg (type, result)
  1005.      const char **type;
  1006.      string *result;
  1007. {
  1008.   const char *start = *type;
  1009.  
  1010.   if (!do_type (type, result))
  1011.     return 0;
  1012.   remember_type (start, *type - start);
  1013.   return 1;
  1014. }
  1015.  
  1016. static void
  1017. remember_type (start, len)
  1018.      const char *start;
  1019.      int len;
  1020. {
  1021.   char *tem;
  1022.  
  1023.   if (ntypes >= typevec_size)
  1024.     {
  1025.       if (typevec_size == 0)
  1026.     {
  1027.       typevec_size = 3;
  1028.       typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
  1029.     }
  1030.       else
  1031.     {
  1032.       typevec_size *= 2;
  1033.       typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
  1034.     }
  1035.     }
  1036.   tem = (char *) xmalloc (len + 1);
  1037.   memcpy (tem, start, len);
  1038.   tem[len] = '\0';
  1039.   typevec[ntypes++] = tem;
  1040. }
  1041.  
  1042. /* `decl' must be already initialised, usually non-empty;
  1043.    it won't be freed on failure */
  1044.  
  1045. static int
  1046. do_args (type, decl)
  1047.      const char **type;
  1048.      string *decl;
  1049. {
  1050.   string arg;
  1051.   int need_comma = 0;
  1052.  
  1053.   string_append (decl, "(");
  1054.  
  1055.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  1056.     {
  1057.       if (**type == 'N')
  1058.     {
  1059.       int r;
  1060.       int t;
  1061.       *type += 1;
  1062.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  1063.         return 0;
  1064.       while (--r >= 0)
  1065.         {
  1066.           const char *tem = typevec[t];
  1067.           if (need_comma)
  1068.         string_append (decl, ", ");
  1069.           if (!do_arg (&tem, &arg))
  1070.         return 0;
  1071.           string_appends (decl, &arg);
  1072.           string_delete (&arg);
  1073.           need_comma = 1;
  1074.         }
  1075.     }
  1076.       else
  1077.     {
  1078.       if (need_comma)
  1079.         string_append (decl, ", ");
  1080.       if (!do_arg (type, &arg))
  1081.         return 0;
  1082.       string_appends (decl, &arg);
  1083.       string_delete (&arg);
  1084.       need_comma = 1;
  1085.     }
  1086.     }
  1087.  
  1088.   if (**type == 'v')
  1089.     *type += 1;
  1090.   else if (**type == 'e')
  1091.     {
  1092.       *type += 1;
  1093.       if (need_comma)
  1094.     string_append (decl, ",");
  1095.       string_append (decl, "...");
  1096.     }
  1097.  
  1098.   string_append (decl, ")");
  1099.   return 1;
  1100. }
  1101.  
  1102. static void
  1103. munge_function_name (name)
  1104.      string *name;
  1105. {
  1106.   if (string_empty (name))
  1107.     return;
  1108.  
  1109.   if (name->p - name->b >= 3 
  1110.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
  1111.     {
  1112.       int i;
  1113.       /* see if it's an assignment expression */
  1114.       if (name->p - name->b >= 10 /* op$assign_ */
  1115.       && memcmp (name->b + 3, "assign_", 7) == 0)
  1116.     {
  1117.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1118.         {
  1119.           int len = name->p - name->b - 10;
  1120.           if (strlen (optable[i].in) == len
  1121.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  1122.         {
  1123.           string_clear (name);
  1124.           string_append (name, "operator");
  1125.           string_append (name, optable[i].out);
  1126.           string_append (name, "=");
  1127.           return;
  1128.         }
  1129.         }
  1130.     }
  1131.       else
  1132.     {
  1133.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1134.         {
  1135.           int len = name->p - name->b - 3;
  1136.           if (strlen (optable[i].in) == len 
  1137.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  1138.         {
  1139.           string_clear (name);
  1140.           string_append (name, "operator");
  1141.           string_append (name, optable[i].out);
  1142.           return;
  1143.         }
  1144.         }
  1145.     }
  1146.       return;
  1147.     }
  1148.   else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0)
  1149.     {
  1150.       /* type conversion operator */
  1151.       string type;
  1152.       const char *tem = name->b + 5;
  1153.       if (do_type (&tem, &type))
  1154.     {
  1155.       string_clear (name);
  1156.       string_append (name, "operator ");
  1157.       string_appends (name, &type);
  1158.       string_delete (&type);
  1159.       return;
  1160.     }
  1161.     }
  1162.   /* ANSI.  */
  1163.   else if (name->b[2] == 'o' && name->b[3] == 'p')
  1164.     {
  1165.       /* type conversion operator.  */
  1166.       string type;
  1167.       const char *tem = name->b + 4;
  1168.       if (do_type (&tem, &type))
  1169.     {
  1170.       string_clear (name);
  1171.       string_append (name, "operator ");
  1172.       string_appends (name, &type);
  1173.       string_delete (&type);
  1174.       return;
  1175.     }
  1176.     }
  1177.   else if (name->b[2] >= 'a' && name->b[2] <= 'z'
  1178.        && name->b[3] >= 'a' && name->b[3] <= 'z')
  1179.     {
  1180.       int i;
  1181.  
  1182.       if (name->b[4] == '\0')
  1183.     {
  1184.       /* Operator.  */
  1185.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1186.         {
  1187.           if (strlen (optable[i].in) == 2
  1188.           && memcmp (optable[i].in, name->b + 2, 2) == 0)
  1189.         {
  1190.           string_clear (name);
  1191.           string_append (name, "operator");
  1192.           string_append (name, optable[i].out);
  1193.           return;
  1194.         }
  1195.         }
  1196.     }
  1197.       else
  1198.     {
  1199.       if (name->b[2] != 'a' || name->b[5] != '\0')
  1200.         return;
  1201.       /* Assignment.  */
  1202.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1203.         {
  1204.           if (strlen (optable[i].in) == 3
  1205.           && memcmp (optable[i].in, name->b + 2, 3) == 0)
  1206.         {
  1207.           string_clear (name);
  1208.           string_append (name, "operator");
  1209.           string_append (name, optable[i].out);
  1210.           return;
  1211.         }
  1212.         }
  1213.     }
  1214.     }
  1215. }
  1216.  
  1217. /* a mini string-handling package */
  1218.  
  1219. static void
  1220. string_need (s, n)
  1221.      string *s;
  1222.      int n;
  1223. {
  1224.   if (s->b == NULL)
  1225.     {
  1226.       if (n < 32)
  1227.     n = 32;
  1228.       s->p = s->b = (char *) xmalloc (n);
  1229.       s->e = s->b + n;
  1230.     }
  1231.   else if (s->e - s->p < n)
  1232.     {
  1233.       int tem = s->p - s->b;
  1234.       n += tem;
  1235.       n *= 2;
  1236.       s->b = (char *) xrealloc (s->b, n);
  1237.       s->p = s->b + tem;
  1238.       s->e = s->b + n;
  1239.     }
  1240. }
  1241.  
  1242. static void
  1243. string_delete (s)
  1244.      string *s;
  1245. {
  1246.   if (s->b != NULL)
  1247.     {
  1248.       free (s->b);
  1249.       s->b = s->e = s->p = NULL;
  1250.     }
  1251. }
  1252.  
  1253. static void
  1254. string_init (s)
  1255.      string *s;
  1256. {
  1257.   s->b = s->p = s->e = NULL;
  1258. }
  1259.  
  1260. static void 
  1261. string_clear (s)
  1262.      string *s;
  1263. {
  1264.   s->p = s->b;
  1265. }
  1266.  
  1267. static int
  1268. string_empty (s)
  1269.      string *s;
  1270. {
  1271.   return s->b == s->p;
  1272. }
  1273.  
  1274. static void
  1275. string_append (p, s)
  1276.      string *p;
  1277.      const char *s;
  1278. {
  1279.   int n;
  1280.   if (s == NULL || *s == '\0')
  1281.     return;
  1282.   n = strlen (s);
  1283.   string_need (p, n);
  1284.   memcpy (p->p, s, n);
  1285.   p->p += n;
  1286. }
  1287.  
  1288. static void
  1289. string_appends (p, s)
  1290.      string *p, *s;
  1291. {
  1292.   int n;
  1293.   if (s->b == s->p)
  1294.     return;
  1295.   n = s->p - s->b;
  1296.   string_need (p, n);
  1297.   memcpy (p->p, s->b, n);
  1298.   p->p += n;
  1299. }
  1300.  
  1301. static void
  1302. string_appendn (p, s, n)
  1303.      string *p;
  1304.      const char *s;
  1305.      int n;
  1306. {
  1307.   if (n == 0)
  1308.     return;
  1309.   string_need (p, n);
  1310.   memcpy (p->p, s, n);
  1311.   p->p += n;
  1312. }
  1313.  
  1314. static void
  1315. string_prepend (p, s)
  1316.      string *p;
  1317.      const char *s;
  1318. {
  1319.   if (s == NULL || *s == '\0')
  1320.     return;
  1321.   string_prependn (p, s, strlen (s));
  1322. }
  1323.  
  1324. #if 0
  1325. static void
  1326. string_prepends (p, s)
  1327.      string *p, *s;
  1328. {
  1329.   if (s->b == s->p)
  1330.     return;
  1331.   string_prependn (p, s->b, s->p - s->b);
  1332. }
  1333. #endif
  1334.  
  1335. static void
  1336. string_prependn (p, s, n)
  1337.      string *p;
  1338.      const char *s;
  1339.      int n;
  1340. {
  1341.   char *q;
  1342.  
  1343.   if (n == 0)
  1344.     return;
  1345.   string_need (p, n);
  1346.   for (q = p->p - 1; q >= p->b; q--)
  1347.     q[n] = q[0];
  1348.   memcpy (p->b, s, n);
  1349.   p->p += n;
  1350. }
  1351.